# -*- coding: utf-8 -*-
"""
时间计算核心引擎
提供各种时间计算功能
"""

import pendulum
from datetime import datetime, timedelta, time
from typing import Dict, List, Optional, Tuple, Union


class TimeCalculator:
    """时间计算器核心类"""
    
    def __init__(self):
        """初始化时间计算器"""
        self.timezone = 'Asia/Shanghai'
    
    def add_time(self, base_time: Union[str, datetime, time], 
                 hours: int = 0, minutes: int = 0, seconds: int = 0) -> Dict:
        """
        时间加减法
        
        Args:
            base_time: 基础时间
            hours: 要加减的小时数
            minutes: 要加减的分钟数
            seconds: 要加减的秒数
            
        Returns:
            包含计算结果的字典
        """
        try:
            # 转换为pendulum时间对象
            if isinstance(base_time, str):
                # 解析时间字符串 (HH:MM:SS 或 HH:MM)
                if len(base_time.split(':')) == 2:
                    base_time += ':00'
                base_dt = pendulum.parse(f"2000-01-01 {base_time}", tz=self.timezone)
            elif isinstance(base_time, time):
                base_dt = pendulum.datetime(2000, 1, 1, base_time.hour, base_time.minute, 
                                          base_time.second, tz=self.timezone)
            elif isinstance(base_time, datetime):
                base_dt = pendulum.instance(base_time, tz=self.timezone)
            else:
                base_dt = base_time
            
            # 计算结果时间
            result_dt = base_dt.add(hours=hours, minutes=minutes, seconds=seconds)
            
            # 检查是否跨天
            days_diff = (result_dt.date() - base_dt.date()).days
            
            result = {
                'base_time': base_dt,
                'result_time': result_dt,
                'hours_added': hours,
                'minutes_added': minutes,
                'seconds_added': seconds,
                'total_seconds_added': hours * 3600 + minutes * 60 + seconds,
                'formatted_base': base_dt.format('HH:mm:ss'),
                'formatted_result': result_dt.format('HH:mm:ss'),
                'base_12hour': base_dt.format('hh:mm:ss A'),
                'result_12hour': result_dt.format('hh:mm:ss A'),
                'days_crossed': days_diff,
                'is_next_day': days_diff > 0,
                'is_prev_day': days_diff < 0,
                'result_date': result_dt.format('YYYY年MM月DD日') if days_diff != 0 else None
            }
            
            return result
            
        except Exception as e:
            raise ValueError(f"时间计算错误: {e}")
    
    def calculate_time_interval(self, start_time: Union[str, datetime, time], 
                               end_time: Union[str, datetime, time], 
                               same_day: bool = True) -> Dict:
        """
        计算两个时间之间的间隔
        
        Args:
            start_time: 开始时间
            end_time: 结束时间
            same_day: 是否为同一天
            
        Returns:
            包含间隔信息的字典
        """
        try:
            # 转换时间
            if isinstance(start_time, str):
                if len(start_time.split(':')) == 2:
                    start_time += ':00'
                start_dt = pendulum.parse(f"2000-01-01 {start_time}", tz=self.timezone)
            elif isinstance(start_time, time):
                start_dt = pendulum.datetime(2000, 1, 1, start_time.hour, start_time.minute, 
                                           start_time.second, tz=self.timezone)
            else:
                start_dt = start_time
            
            if isinstance(end_time, str):
                if len(end_time.split(':')) == 2:
                    end_time += ':00'
                base_date = "2000-01-01" if same_day else "2000-01-02"
                end_dt = pendulum.parse(f"{base_date} {end_time}", tz=self.timezone)
            elif isinstance(end_time, time):
                day_offset = 0 if same_day else 1
                end_dt = pendulum.datetime(2000, 1, 1 + day_offset, end_time.hour, 
                                         end_time.minute, end_time.second, tz=self.timezone)
            else:
                end_dt = end_time
            
            # 如果结束时间早于开始时间且设置为同一天，则认为跨天
            if same_day and end_dt < start_dt:
                end_dt = end_dt.add(days=1)
            
            # 计算间隔
            diff = end_dt - start_dt
            total_seconds = int(diff.total_seconds())
            
            hours = total_seconds // 3600
            remaining_seconds = total_seconds % 3600
            minutes = remaining_seconds // 60
            seconds = remaining_seconds % 60
            
            result = {
                'start_time': start_dt,
                'end_time': end_dt,
                'total_seconds': total_seconds,
                'total_minutes': total_seconds // 60,
                'total_hours': total_seconds / 3600,
                'hours': hours,
                'minutes': minutes,
                'seconds': seconds,
                'formatted_start': start_dt.format('HH:mm:ss'),
                'formatted_end': end_dt.format('HH:mm:ss'),
                'start_12hour': start_dt.format('hh:mm:ss A'),
                'end_12hour': end_dt.format('hh:mm:ss A'),
                'interval_display': self._format_time_interval(hours, minutes, seconds),
                'is_cross_day': (end_dt.date() - start_dt.date()).days > 0
            }
            
            return result
            
        except Exception as e:
            raise ValueError(f"时间间隔计算错误: {e}")
    
    def add_work_hours(self, start_time: Union[str, datetime, time], 
                      work_hours: float, work_day_start: str = "09:00", 
                      work_day_end: str = "17:00") -> Dict:
        """
        计算工作时间（考虑工作日时间限制）
        
        Args:
            start_time: 开始时间
            work_hours: 要加的工作小时数
            work_day_start: 工作日开始时间
            work_day_end: 工作日结束时间
            
        Returns:
            包含计算结果的字典
        """
        try:
            # 解析工作日时间
            work_start = pendulum.parse(f"2000-01-01 {work_day_start}", tz=self.timezone).time()
            work_end = pendulum.parse(f"2000-01-01 {work_day_end}", tz=self.timezone).time()
            daily_work_hours = (pendulum.parse(f"2000-01-01 {work_day_end}", tz=self.timezone) - 
                              pendulum.parse(f"2000-01-01 {work_day_start}", tz=self.timezone)).total_seconds() / 3600
            
            # 转换开始时间
            if isinstance(start_time, str):
                if len(start_time.split(':')) == 2:
                    start_time += ':00'
                start_dt = pendulum.parse(f"2000-01-01 {start_time}", tz=self.timezone)
            elif isinstance(start_time, time):
                start_dt = pendulum.datetime(2000, 1, 1, start_time.hour, start_time.minute, 
                                           start_time.second, tz=self.timezone)
            else:
                start_dt = start_time
            
            current_dt = start_dt
            remaining_hours = work_hours
            days_added = 0
            
            while remaining_hours > 0:
                current_time = current_dt.time()
                
                # 如果当前时间在工作时间之前，调整到工作开始时间
                if current_time < work_start:
                    current_dt = current_dt.replace(hour=work_start.hour, minute=work_start.minute, 
                                                   second=work_start.second)
                
                # 如果当前时间在工作时间之后，跳到下一个工作日
                elif current_time >= work_end:
                    current_dt = current_dt.add(days=1).replace(hour=work_start.hour, 
                                                              minute=work_start.minute, second=work_start.second)
                    days_added += 1
                    continue
                
                # 计算当天剩余工作时间
                end_of_day = current_dt.replace(hour=work_end.hour, minute=work_end.minute, second=work_end.second)
                remaining_today = (end_of_day - current_dt).total_seconds() / 3600
                
                if remaining_hours <= remaining_today:
                    # 当天就能完成
                    current_dt = current_dt.add(hours=remaining_hours)
                    remaining_hours = 0
                else:
                    # 需要跨天
                    remaining_hours -= remaining_today
                    current_dt = current_dt.add(days=1).replace(hour=work_start.hour, 
                                                              minute=work_start.minute, second=work_start.second)
                    days_added += 1
            
            result = {
                'start_time': start_dt,
                'result_time': current_dt,
                'work_hours_added': work_hours,
                'days_spanned': days_added,
                'work_day_start': work_day_start,
                'work_day_end': work_day_end,
                'daily_work_hours': daily_work_hours,
                'formatted_start': start_dt.format('HH:mm:ss'),
                'formatted_result': current_dt.format('HH:mm:ss'),
                'result_date': current_dt.format('YYYY年MM月DD日') if days_added > 0 else None
            }
            
            return result
            
        except Exception as e:
            raise ValueError(f"工作时间计算错误: {e}")
    
    def convert_timezone(self, time_obj: Union[str, datetime], 
                        from_tz: str, to_tz: str) -> Dict:
        """
        时区转换
        
        Args:
            time_obj: 时间对象
            from_tz: 源时区
            to_tz: 目标时区
            
        Returns:
            包含转换结果的字典
        """
        try:
            # 转换时间
            if isinstance(time_obj, str):
                source_dt = pendulum.parse(time_obj, tz=from_tz)
            elif isinstance(time_obj, datetime):
                source_dt = pendulum.instance(time_obj, tz=from_tz)
            else:
                source_dt = time_obj
            
            # 转换到目标时区
            target_dt = source_dt.in_timezone(to_tz)
            
            result = {
                'source_time': source_dt,
                'target_time': target_dt,
                'from_timezone': from_tz,
                'to_timezone': to_tz,
                'source_formatted': source_dt.format('YYYY年MM月DD日 HH:mm:ss'),
                'target_formatted': target_dt.format('YYYY年MM月DD日 HH:mm:ss'),
                'source_12hour': source_dt.format('YYYY年MM月DD日 hh:mm:ss A'),
                'target_12hour': target_dt.format('YYYY年MM月DD日 hh:mm:ss A'),
                'time_difference': (target_dt - source_dt).total_seconds() / 3600
            }
            
            return result
            
        except Exception as e:
            raise ValueError(f"时区转换错误: {e}")
    
    def _format_time_interval(self, hours: int, minutes: int, seconds: int) -> str:
        """格式化时间间隔显示"""
        parts = []
        
        if hours > 0:
            parts.append(f"{hours}小时")
        if minutes > 0:
            parts.append(f"{minutes}分钟")
        if seconds > 0:
            parts.append(f"{seconds}秒")
        
        if not parts:
            return "0秒"
        
        return "".join(parts)
    
    def get_current_time_info(self) -> Dict:
        """获取当前时间的详细信息"""
        try:
            now = pendulum.now(self.timezone)
            
            result = {
                'current_time': now,
                'formatted_24h': now.format('HH:mm:ss'),
                'formatted_12h': now.format('hh:mm:ss A'),
                'full_datetime': now.format('YYYY年MM月DD日 HH:mm:ss dddd'),
                'timestamp': now.timestamp(),
                'timezone': '北京时间 (UTC+8)',
                'utc_time': now.in_timezone('UTC'),
                'utc_formatted': now.in_timezone('UTC').format('YYYY年MM月DD日 HH:mm:ss'),
                'hour': now.hour,
                'minute': now.minute,
                'second': now.second,
                'microsecond': now.microsecond
            }
            
            return result
            
        except Exception as e:
            raise ValueError(f"获取当前时间信息错误: {e}")
